home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / mint / mint104s.zoo / mint.src / dosdir.c < prev    next >
C/C++ Source or Header  |  1993-03-08  |  30KB  |  1,314 lines

  1. /*
  2. Copyright 1990,1991,1992 Eric R. Smith.
  3. Copyright 1992,1993 Atari Corporation.
  4. All rights reserved.
  5. */
  6.  
  7. /* DOS directory functions */
  8.  
  9. #include "mint.h"
  10.  
  11. /* change to a new drive: should always return a map of valid drives */
  12.  
  13. long ARGS_ON_STACK
  14. d_setdrv(d)
  15.     int d;
  16. {
  17.     long r;
  18.     extern long dosdrvs;    /* in filesys.c */
  19.  
  20.     r = drvmap() | dosdrvs | PSEUDODRVS;
  21.  
  22.     TRACE(("Dsetdrv(%d)", d));
  23.     if (d < 0 || d >= NUM_DRIVES || (r & (1L << d)) == 0) {
  24.         DEBUG(("Dsetdrv: invalid drive %d", d));
  25.         return r;
  26.     }
  27.  
  28.     curproc->base->p_defdrv = curproc->curdrv = d;
  29.     return r;
  30. }
  31.  
  32.  
  33. long ARGS_ON_STACK
  34. d_getdrv()
  35. {
  36.     TRACE(("Dgetdrv"));
  37.     return curproc->curdrv;
  38. }
  39.  
  40. long ARGS_ON_STACK
  41. d_free(buf, d)
  42.     long *buf;
  43.     int d;
  44. {
  45.     fcookie *dir = 0;
  46.     extern int aliasdrv[];
  47.  
  48.     TRACE(("Dfree(%d)", d));
  49.  
  50. /* drive 0 means current drive, otherwise it's d-1 */
  51.     if (d)
  52.         d = d-1;
  53.     else
  54.         d = curproc->curdrv;
  55.  
  56. /* Hack to make programs (like df) which use drive
  57.  * information from Fxattr() work more often.
  58.  * BUG: this works only if the drive is a root,
  59.  * a current directory or an alias, or one of the
  60.  * standard drives.
  61.  */
  62.     if (d < 0 || d >= NUM_DRIVES) {
  63.         int i;
  64.  
  65.         for (i = 0; i < NUM_DRIVES; i++) {
  66.             if (aliasdrv[i] == d) {
  67.                 d = i;
  68.                 goto aliased;
  69.             }
  70.             if (curproc->curdir[i].dev == d) {
  71.                 dir = &curproc->curdir[i];
  72.             } else if (curproc->root[i].dev == d) {
  73.                 dir = &curproc->root[i];
  74.             }
  75.         }
  76.         if (dir && dir->fs) {
  77.             return (*dir->fs->dfree)(dir, buf);
  78.         }
  79.         return EDRIVE;
  80.     }
  81.  
  82. /* check for a media change -- we don't care much either way, but it
  83.  * does keep the results more accurate
  84.  */
  85.     (void)disk_changed(d);
  86.  
  87. aliased:
  88.  
  89. /* use current directory, not root, since it's more likely that
  90.  * programs are interested in the latter (this makes U: work much
  91.  * better)
  92.  */
  93.     dir = &curproc->curdir[d];
  94.     if (!dir->fs) {
  95.         DEBUG(("Dfree: bad drive"));
  96.         return EDRIVE;
  97.     }
  98.  
  99.     return (*dir->fs->dfree)(dir, buf);
  100. }
  101.  
  102. /* temp1 is a convenient place for path2fs puts the last component of
  103.  *   the path name
  104.  */
  105.  
  106. extern char temp1[PATH_MAX];    /* in filesys.c */
  107.  
  108. long ARGS_ON_STACK
  109. d_create(path)
  110.     const char *path;
  111. {
  112.     fcookie dir;
  113.     long r;
  114.  
  115.     TRACE(("Dcreate(%s)", path));
  116.  
  117.     r = path2cookie(path, temp1, &dir);
  118.     if (r) {
  119.         DEBUG(("Dcreate(%s): returning %ld", path, r));
  120.         return r;    /* an error occured */
  121.     }
  122. /* check for write permission on the directory */
  123.     r = dir_access(&dir, S_IWOTH);
  124.     if (r) {
  125.         DEBUG(("Dcreate(%s): access to directory denied",path));
  126.         release_cookie(&dir);
  127.         return r;
  128.     }
  129.     r = (*dir.fs->mkdir)(&dir, temp1, DEFAULT_DIRMODE & ~curproc->umask);
  130.     release_cookie(&dir);
  131.     return r;
  132. }
  133.  
  134. long ARGS_ON_STACK
  135. d_delete(path)
  136.     const char *path;
  137. {
  138.     fcookie parentdir, targdir;
  139.     long r;
  140.     PROC *p;
  141.     int i;
  142.     XATTR xattr;
  143.  
  144.     TRACE(("Ddelete(%s)", path));
  145.  
  146.     r = path2cookie(path, temp1, &parentdir);
  147.  
  148.     if (r) {
  149.         DEBUG(("Ddelete(%s): error %lx", path, r));
  150.         release_cookie(&parentdir);
  151.         return r;
  152.     }
  153. /* check for write permission on the directory which the target
  154.  * is located
  155.  */
  156.     if ((r = dir_access(&parentdir, S_IWOTH)) != 0) {
  157.         DEBUG(("Ddelete(%s): access to directory denied", path));
  158.         release_cookie(&parentdir);
  159.         return r;
  160.     }
  161.  
  162. /* now get the info on the file itself */
  163.  
  164.     r = relpath2cookie(&parentdir, temp1, NULL, &targdir, 0);
  165.     if (r) {
  166. bailout:
  167.         release_cookie(&parentdir);
  168.         DEBUG(("Ddelete: error %ld on %s", r, path));
  169.         return r;
  170.     }
  171.     if ((r = (*targdir.fs->getxattr)(&targdir, &xattr)) != 0) {
  172.         release_cookie(&targdir);
  173.         goto bailout;
  174.     }
  175.  
  176. /* if the "directory" is a symbolic link, really unlink it */
  177.     if ( (xattr.mode & S_IFMT) == S_IFLNK ) {
  178.         r = (*parentdir.fs->remove)(&parentdir, temp1);
  179.     } else if ( (xattr.mode & S_IFMT) != S_IFDIR ) {
  180.         DEBUG(("Ddelete: %s is not a directory", path));
  181.         r = EPTHNF;
  182.     } else {
  183.  
  184. /* don't delete anyone else's root or current directory */
  185.         for (p = proclist; p; p = p->gl_next) {
  186.         if (p->wait_q == ZOMBIE_Q || p->wait_q == TSR_Q)
  187.             continue;
  188.         for (i = 0; i < NUM_DRIVES; i++) {
  189.             if (samefile(&targdir, &p->root[i])) {
  190.                 DEBUG(("Ddelete: directory %s is a root directory",
  191.                     path));
  192. noaccess:
  193.                 release_cookie(&targdir);
  194.                 release_cookie(&parentdir);
  195.                 return EACCDN;
  196.             } else if (samefile(&targdir, &p->curdir[i])) {
  197.                 if (i == p->curdrv && p != curproc) {
  198.                     DEBUG(("Ddelete: directory %s is in use",
  199.                         path));
  200.                     goto noaccess;
  201.                 } else {
  202.                     release_cookie(&p->curdir[i]);
  203.                     dup_cookie(&p->curdir[i], &p->root[i]);
  204.                 } 
  205.             }
  206.         }
  207.         }
  208.         release_cookie(&targdir);
  209.         r = (*parentdir.fs->rmdir)(&parentdir, temp1);
  210.     }
  211.     release_cookie(&parentdir);
  212.     return r;
  213. }
  214.  
  215. long ARGS_ON_STACK
  216. d_setpath(path)
  217.     const char *path;
  218. {
  219.     fcookie dir;
  220.     int drv = curproc->curdrv;
  221.     int i;
  222.     char c;
  223.     long r;
  224.     XATTR xattr;
  225.  
  226.     TRACE(("Dsetpath(%s)", path));
  227.  
  228.     r = path2cookie(path, follow_links, &dir);
  229.  
  230.     if (r) {
  231.         DEBUG(("Dsetpath(%s): returning %ld", path, r));
  232.         return r;
  233.     }
  234.  
  235.     if (path[0] && path[1] == ':') {
  236.         c = *path;
  237.         if (c >= 'a' && c <= 'z')
  238.             drv = c-'a';
  239.         else if (c >= 'A' && c <= 'Z')
  240.             drv = c-'A';
  241.     }
  242.  
  243.     r = (*dir.fs->getxattr)(&dir, &xattr);
  244.  
  245.     if (r < 0) {
  246.         DEBUG(("Dsetpath: file '%s': attributes not found", path));
  247.         release_cookie(&dir);
  248.         return r;
  249.     }
  250.  
  251.     if (!(xattr.attr & FA_DIR)) {
  252.         DEBUG(("Dsetpath(%s): not a directory",path));
  253.         release_cookie(&dir);
  254.         return EPTHNF;
  255.     }
  256.  
  257. /*
  258.  * watch out for symbolic links; if c:\foo is a link to d:\bar, then
  259.  * "cd c:\foo" should also change the drive to d:
  260.  */
  261.     if (drv != UNIDRV && dir.dev != curproc->root[drv].dev) {
  262.         for (i = 0; i < NUM_DRIVES; i++) {
  263.             if (curproc->root[i].dev == dir.dev &&
  264.                 curproc->root[i].fs == dir.fs) {
  265.                 if (drv == curproc->curdrv)
  266.                     curproc->curdrv = i;
  267.                 drv = i;
  268.                 break;
  269.             }
  270.         }
  271.     }
  272.     release_cookie(&curproc->curdir[drv]);
  273.     curproc->curdir[drv] = dir;
  274.     return 0;
  275. }
  276.  
  277. /* jr: like d_getpath, except that the caller provides a limit
  278.    for the max. number of characters to be put into the buffer.
  279.    Inspired by POSIX.1, getcwd(), 5.2.2 */
  280.  
  281. long ARGS_ON_STACK
  282. d_getcwd(path, drv, size)
  283.     char *path;
  284.     int drv, size;
  285. {
  286.     fcookie *dir, *root;
  287.     long r;
  288.     char buf[PATH_MAX];
  289.     FILESYS *fs;
  290.  
  291.     TRACE(("Dgetcwd(%c, %d)", drv + '@', size));
  292.     if (drv < 0 || drv > NUM_DRIVES)
  293.         return EDRIVE;
  294.  
  295.     drv = (drv == 0) ? curproc->curdrv : drv-1;
  296.  
  297.     root = &curproc->root[drv];
  298.  
  299.     if (!root->fs) {    /* maybe not initialized yet? */
  300.         changedrv(drv);
  301.         root = &curproc->curdir[drv];
  302.         if (!root->fs)
  303.             return EDRIVE;
  304.     }
  305.     fs = root->fs;
  306.     dir = &curproc->curdir[drv];
  307.  
  308.     if (!(fs->fsflags & FS_LONGPATH)) {
  309.         r = (*fs->getname)(root, dir, buf, PATH_MAX);
  310.         if (r) return r;
  311.         if (strlen(buf) < size) {
  312.             strcpy(path, buf);
  313.             return 0;
  314.         } else {
  315.             return ERANGE;
  316.         }
  317.     }
  318.     return (*fs->getname)(root, dir, path, size);
  319. }
  320.  
  321. long ARGS_ON_STACK
  322. d_getpath(path, drv)
  323.     char *path;
  324.     int drv;
  325. {
  326.     TRACE(("Dgetpath(%c)", drv + '@'));
  327.     return d_getcwd(path, drv, PATH_MAX);
  328. }
  329.  
  330. long ARGS_ON_STACK
  331. f_setdta(dta)
  332.     DTABUF *dta;
  333. {
  334.  
  335.     TRACE(("Fsetdta: %lx", dta));
  336.     curproc->dta = dta;
  337.     curproc->base->p_dta = (char *)dta;
  338.     return 0;
  339. }
  340.  
  341. long ARGS_ON_STACK
  342. f_getdta()
  343. {
  344.     long r;
  345.  
  346.     r = (long)curproc->dta;
  347.     TRACE(("Fgetdta: returning %lx", r));
  348.     return r;
  349. }
  350.  
  351. /*
  352.  * Fsfirst/next are actually implemented in terms of opendir/readdir/closedir.
  353.  */
  354.  
  355. long ARGS_ON_STACK
  356. f_sfirst(path, attrib)
  357.     const char *path;
  358.     int attrib;
  359. {
  360.     char *s, *slash;
  361.     FILESYS *fs;
  362.     fcookie dir, newdir;
  363.     DTABUF *dta;
  364.     DIR *dirh;
  365.     XATTR xattr;
  366.     long r;
  367.     int i, havelabel;
  368.  
  369.     TRACE(("Fsfirst(%s, %x)", path, attrib));
  370.  
  371.     r = path2cookie(path, temp1, &dir);
  372.  
  373.     if (r) {
  374.         DEBUG(("Fsfirst(%s): path2cookie returned %ld", path, r));
  375.         return r;
  376.     }
  377.  
  378. /*
  379.  * we need to split the last name (which may be a pattern) off from
  380.  * the rest of the path, even if FS_KNOPARSE is true
  381.  */
  382.     slash = 0;
  383.     s = temp1;
  384.     while (*s) {
  385.         if (*s == '\\')
  386.             slash = s;
  387.         s++;
  388.     }
  389.  
  390.     if (slash) {
  391.         *slash++ =